package com.dlc.felear.xiaoensale.deviceControlSf;

import android.text.TextUtils;
import android.util.Log;

import com.dlc.felear.xiaoensale.constant.Constant;
import com.dlc.felear.xiaoensale.dlc_serial_port.DlcSerialPortClient;
import com.dlc.felear.xiaoensale.factory.CmdList;

import org.simple.eventbus.EventBus;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class HcSfControl implements HcSfControlUtil.SfResultCallback {
    private static final String TAG = "HcSfControl";

    private static HcSfControl instance;
    private ScheduledExecutorService scheduledThreadPool;
    private String serialNo;
    private ArrayBlockingQueue<byte[]> cmds;
    /**
     * 控制锅体的伺服
     */
    private HcSfControlUtil hcSfControlUtil2;
    private SfRunresult callback;
    private int[] position1s = {-120000, -40000, 0, -70000, -60000, -55000, -12000, 0, -150000, 0};

    /**
     * M600炒菜机锅体位置参数
     */
    private int[] position2s = {-300000, -170000, 0, -190000, -170000, -150000, -100000, 170000, -340000, -340000};
    private HcSfControl(String serialNo,String driverType) {
        try {
            this.serialNo = serialNo;
            if(TextUtils.equals(driverType,"M600")){
                hcSfControlUtil2 = new HcSfControlUtil(2, this, this, position2s,driverType);
            }else {
                hcSfControlUtil2 = new HcSfControlUtil(2, this, this, position1s,driverType);
            }
            this.scheduledThreadPool = new ScheduledThreadPoolExecutor(2);
            cmds = new ArrayBlockingQueue<>(50);
            startTimer();
            startLoop();
            Log.e(TAG, "serialNo=" + serialNo);
        } catch (Exception e) {
            log(e.getMessage());
        }
    }

    public void setSfRunresultCallback(SfRunresult callback) {
        this.callback = callback;
    }


    private void startTimer() {
        scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                try {
                    hcSfControlUtil2.loop();
//                    log("startTimer");
                } catch (Exception e) {
                    log(e.getMessage());
                }
            }
        }, 2000, 200, TimeUnit.MILLISECONDS);
    }

    /**
     * 指令分发队列
     */
    private void startLoop() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    byte[] data = null;
                    while ((data = cmds.take()) != null) {
                        sendCmd(data);
                        Thread.sleep(70);
                    }
                } catch (Exception e) {
                    startLoop();
                }

            }
        }).start();
    }

    public static HcSfControl getInstance(String serialNo,String driverType) {
        if (instance == null) {
            synchronized (HcSfControl.class) {
                if (instance == null) {
                    instance = new HcSfControl(serialNo,driverType);
                }
            }
        }

        return instance;
    }

    public void recieveData(byte[] data) {
//        log("recieveData data=" + HexUtil.bytes2HexString(data));
        if (!CmdList.checkDataComplete(data)) {
//            log("recieveData 指令不完整 data=" + HexUtil.bytes2HexString(data));
            return;
        }
        if (data[0] == 2) {
            hcSfControlUtil2.recieveData(data);
//            log("recieveData addr=" + data[0]);
        }
    }

    /**
     * 添加指令
     *
     * @param data
     */
    public void sendCmdToQueue(byte[] data) {
        try {
            cmds.offer(data);
        } catch (Exception e) {

        }
    }

    /**
     * @param data
     */
    public synchronized void resetMapValue(byte[] data, int addr) {
        try {
            sendCmd(data);
        } catch (Exception e) {
            log(e.getMessage());
        }
    }

    private void sendCmd(byte[] data) {
//        log("send data:" + HexUtil.bytes2HexString(data) + " 等待发送指令:" + cmds.size());
        DlcSerialPortClient.getInstance().send(serialNo, data);
    }

    private void log(String msg) {
        if (!TextUtils.isEmpty(msg)) {
            Log.e(TAG, msg);
        }
    }


    /**
     * 点动
     *
     * @param addr
     * @param flag
     */
    public void singgleStep(int addr, int flag) {
        hcSfControlUtil2.singgleStepRun(flag);
    }

    /**
     * 执行
     *
     * @param addr
     * @param run
     */
    public void excutSfRun(int addr, boolean run) {
        hcSfControlUtil2.runExecute(run);
    }


    /**
     * 重置编码器
     *
     * @param addr
     */
    public void resetBmq(int addr) {
        hcSfControlUtil2.resetBmq();
    }

    /**
     * 清除报警信息
     *
     * @param addr
     */
    public void resetSf(int addr) {
        hcSfControlUtil2.resetSf();
    }

    /**
     * 设置原点
     *
     * @param addr
     */
    public void resetYd(int addr) {
        hcSfControlUtil2.resetYd();
    }

    /**
     * 运行到指定位置
     *
     * @param addr
     * @param num
     */
    public void runDesignatedSpot(int addr, int num) {
        hcSfControlUtil2.runDesignatedSpot(num);
        cmds.clear();
    }

    /**
     * 设置脉冲
     *
     * @param addr
     * @param num
     * @param puls
     */
    public void setPuls(int addr, int num, int puls) {
        hcSfControlUtil2.setPlus(num, puls);
    }

    /**
     * 获取报警信息
     *
     * @return
     */
    public String getSfErrMsg() {
        String temp = hcSfControlUtil2.getSfErrMsg();
        return temp;
    }


    @Override
    public void callback(int addr, int errorCode, int position, int puls) {
        if (callback != null) {
            callback.SfRunresultCallback(addr, errorCode, position, puls);
        }
    }


    public interface SfRunresult {
        void SfRunresultCallback(int addr, int errorCode, int position, int puls);
    }

    public int getPosition(int addr) {
        return hcSfControlUtil2.getPosition();
    }

    public void showToastMsg(String msg) {
        log("showToastMsg:" + msg);
        EventBus.getDefault().post(msg, Constant.DEVICE_STATUS_MSG_SHOW);
    }

}
